[Crunchie
	Crunchie is a BASIC utility to crunch BASIC files.
]
[Display
	Use StrongED$Mode=Document for folded and coloured text in this manual.
	Remove the first character of every line to convert to plain text.
]
[Purpose
		delete comments, blank lines, empty statements and spaces
		shorten variable, procedure and function names
		convert SWI names after SYS/SWI to numbers
		convert ASC with literal strings to numbers
		convert constant variables to literal values
		remove debugging statements
		remove unwanted routines
		concatenate lines
		crunch multiple library files to same values
		append crunched libraries to the main program
		allow for Basalt keywords and constants
	Not implemented:
		shorten expressions
]
[Benefits
		takes less memory
		improves performance
		allows debugging that is removed on crunching
		obscures the code - which is not really a benefit
		allows additional features with translation
]
[Syntax
>	*Crunchie [-input] inputfile [-output] outputfile
	-input     (-i)  inputfile    = full name of BASIC file to crunch
	-output    (-o)  outputfile   = full name of crunched file to save
	This may be followed by any of these keywords:
	-variables (-vf) variablefile = optional rules for variable names
	-routines  (-rf) routinefile  = optional rules for PROC/FN names
	-alloff    [-ao]              = switch to disable PROC/FN crunching
	-assemble  (-as)              = switch for assembler mnemonics
	-macros    (-mf) macrofile    = optional rules for assembler macros
	-libraries (-lf) libraryfile  = optional list of libraries to crunch
	-basalt    (-ba)              = switch to preserve Basalt features
	-progress  (-pr)              = switch to report progress in Reporter
	-emptyoff  (-eo)              = switch to keep empty lines
	-swioff    (-so)              = switch to keep SWI names
	-vduoff    (-vo)              = switch to keep VDU debug lines
	-dataoff   (-do)              = switch to keep DATA lines uncrunched
	-nextoff   [-no]              = switch to keep NEXT variables
	-joinoff   (-jo)              = switch to keep lines unjoined
	-defjoin   [-dj]              = switch to join lines after DEF
	-litoff    [-lo]              = switch to disable literal values
	-analysis  [-af] analysisfile = optional file for crunch details
	-append    [-ap] number       = maximum number of appended libraries
	-maxapp    [-ma] number       = maximum size of appended library
	-norem     [-nr]              = switch to remove copyright REM
	An additional feature is to translate a modified program to an executable form:
	-translate (-tr)              = switch to enable translation
	-constants (-cf) constantfile = optional file of constant
	The [] contain the synonyms for keywords.
===============================================================================
	To avoid conflicts, now or with future extensions, do not use single character abbreviations except for -input and -output. However, inputfile and outputfile must be present and do not need keywords, so the minimum command is:
>	*Crunchie inputfile outputfile
	If the !Crunchie applications has been seen, then the command can be:
>	*Crunchie:Crunchie inputfile outputfile
]
[Operation
{Outline
	Crunchie is a single-pass cruncher and relatively straightforward, so it does not need to build lists and analytical structures and is therefore quite fast.
	Translation is more complex and requires two passes.
}
{Use of CRUNCH
	The input program is loaded into Crunchie as a library, with the system variable BASIC$Crunch set. This does the work of the CRUNCH command with parameter %01111, which removes:
		all spaces before statements
		all spaces within statements, which may make a program uneditable
		all REM statements except the first line
		all empty statements
	Note that CRUNCH does not crunch the first line, nor does Crunchie. This should start with REM> and be followed by the name of the file.
	Crunchie also does the work of bit 4 and removes:
		all empty lines
	On completion BASIC$Crunch is set as it was before.
	Note: files being crunched are not actually included in the library list, which prevents any of their routines being looked up by the Crunchie program.
}
{Crunchie names
	Variable and routine name crunching is simple and uses BASIC's own variable handling.
	A unique name can be used for any of float, integer, string, float array, integer array, string array, procedure and function. So all these can coexist: name, name%, name$, name(), name%(), name$(), PROCname and FNname. It is is the name, not the subscript which matters to Crunchie.
	Because a name must contain only identifier characters, Crunchie does not crunch routine names that contain the '@' character. This might be considered a limitation or a feature, depending on programming style.
}
{Crunching method
	Leave all single character names unchanged, on the assumption that the programmer has chosen them for a reason.
	Sustitute two-character names for all remaining names in the order they appear in the program:
		For PROCs and FNs (routines) the first two-letter name is '00'. For subsequent names the first character changes first, '0' to 9' then 'A' to 'Z' then 'a' to 'z', before the second character is changed, '0' to '9','A' to 'Z' then 'a' to 'z'. There are 3844 names. PROCs and FNs have separate lists of names.
		For variables the first two-letter name is 'A0'. For subsequent names the first character changes first, 'A' to 'Z' then 'a' to 'z', before the second character is changed, '0' to '9','A' to 'Z' then 'a' to 'z'. However, some names are excluded because they may cause program errors. There are 3197 names. Integers, strings and floats have separate lists of names as do their equivalent arrays.
	There is an error if the total number of names for a particular type is exceeded.
}
{Assembler mnemonics
	Crunchie does not take account of assembler blocks unless the -assemble or -as switch is used, so mnemonics will be corrupted
}
{Constant variables
	Identify constants variables set by LET statements at the start of the program and substitute their literal values in the rest of the program. The LET keyword should never be necessary in a program otherwise.
	Constants are variables that hold a value that will never be re-assigned during the run of a program. They might be Wimp reason codes or icon numbers, for instance. Before crunching, the program will run, because LET is neutral in assignment
	After crunching the variables are replaced by the literal values assigned to the variables in the LET statements. The program will still run as before. The LET statements are removed from the program, so the variable names can be long and desciptive without penalty.
	It is important that Crunchie sees the LET statements before the variables are used in the program, which means they must be physically at the start, not logically.
!	WARNING: If the value assigned by LET is not a literal value it is unlikely that the program will run correctly after crunching.
	See Translation for another way to implement program constants.
}
{SWI conversion
	Convert SWI name strings following SYS to hexdecimal literal numbers. The number of digits is kept small, but not absolutely minimal. If a SWI name is not known, perhaps because the necessary module is not loaded, then the name string is not converted.
	If Crunchie is set to use assembler then SWI name strings following the mnemonic 'SWI' are also converted.
}
{ASC conversion
	Convert an ASC function followed by a parameter starting with a literal string to a decimal number representing the first character.
	This means there is no penalty in writing, eg:
>	CASE character% OF
>	WHEN ASC"a": ...
}
{CHR$ conversion
	Convert a CHR$ function to a single character literal string. If there is a previous or following concatenated literal string then include the character in that string.
}
{FOR...NEXT variables
	Remove a variable following NEXT. This may gain a little speed and space, but it relies on the program being 'well-formed' - see Modification and Warnings below.
	Remove STEP followed by '1', as redundant.
}
{Single-line THEN
	Remove THEN in single-line IF structure, except when followed by a *command, an implied GOTO line number or '=' as the return from a function . A space is inserted for indirected variables.
}
{Binary conversion
	Convert binary numbers starting with '%' and followed by '0's and '1's to decimal numbers.
	There might be a problem with, eg: 'DIM var% 1010', which BASIC CRUNCH reduces to 'DIMvar%1010', but I think that I have accounted for it. This might be a bug in BASIC.
}
{Debugging lines
	A VDU statement on its own does nothing. This can be used to mark debugging statements, which are removed to the end of the line, eg:
>	VDU:*Report thisvar%
}
{CLI Commands
	Everything following a '*' at the start of a statement to the end of the line is passed to the CLI by BASIC. Crunchie does not crunch such *commands.
	However, if the '*' is followed by '|', this would be treated as a comment by the CLI, so Crunchie deletes the whole *command.
	There are consequences for a couple of *commands:
		If *Report is used to display the value of a variable, the variable name must be excluded when crunched - see Modification below. This is because the name in the program will be crunched, but not in the *command.
		The same condition applies to the use of *Sort to sort arrays.
	These can be avoided by using OSCLI to call the *commands.
}
{Concatenate lines
	Consecutive lines are joined together if doing so does not change the program logic and the combined length of a crunched line is not greater than 256 bytes.
	The logic is simple and only whole lines are joined, so there may be a advantage to putting single statements on their own lines, where possible.
}
{Crunching directives
	A program or library may contain test code, definitions, and segments that have been written, but are not used at present. The directives APPEND and CRUNCH can be used to discard these from the output.
_APPEND
	Think of APPEND as 'application end'.
	If APPEND is found, crunching stops and all following code is ignored.
_CRUNCH ON|OFF
	CRUNCH can be used to discard only speicfic sections of a program, but it has to allow the program to run normally before crunching.
	If  CRUNCH ON is found, all code back to the previous CRUNCH OFF is discarded.
	There is an implicit CRUNCH OFF after the initial REM> line.
	To discard test routines at the start of a library, just put CRUNCH ON after the normal END and before the DEFs.
}
{LOCAL, READ, DIM and VDU
	These statements are followed by an unlimited comma-separated list of arguments.
	If one such statement follows immediately after another of the same type, the two are combined into a single statement, as are any further statements of that type.
	This is also done over line breaks, so there is no penalty in writing:
>	LOCAL xcoord:REM the X cordinate of the centre
>	LOCAL ycoord:REM the Y cordinate of the centre
>	LOCAL radius:REM the radius of the circle
	instead of:
>	LOCAL xcoord,ycoord,radius:REM ...
	LOCAL DATA and LOCAL ERROR statements are not combined.
}
]
[Modification
{Empty lines
	By default Crunchie removes empty lines, which BASIC's CRUNCH does not do, because it could remove lines that are targets for GOTO, GOSUB or RESTORE. To disable this, include the switch -emptyoff or -eo.
}
{SWI conversion
	By default Crunchie converts SWI names as strings following SYS to literal hexadecimal numbers. To disable this include the switch -swioff or -so.
}
{Debugging lines
	By default Crunchie removes a VDU statement on its own and everything following on the same line. To disable this include the switch -vduoff or -vo.
}
{Literal values
	By default Crunchie substitutes literal values for variables assigned using LET. To disable this include the switch -litoff or -lo.
}
{Assembler blocks
	By default Crunchie crunches the whole program in the same way. This applies to mnemonics in sections of assembler code, which would be rendered unrecognisable. If a program contains assembler, use the keyword -assemble or -as.
	This will cause Crunchie to check names in the file 'Assembler' in the 'Files' directory. This file is MessageTrans file prepared to exclude mnemonics from crunching. Crunchie expects mnemonics to be in uppercase, but condition codes can be in either case. If there is a rule that is not included, this file might be modified.
	The instructions AND EOR OR[R] MOVE[Q] VDU[P] are tokenised as keywords by BASIC and are treated separately.
	The instructions OPT LSR ASR LSL ASL ROR RRX cannot be the start of a variable within assembler code; think [OPTpass% or LSLr1.
	If Crunchie is set to use assembler then, in addition to preserving mnemonics, it does:
		comments after ';' or '\' are removed to the next ':' or end of line. Note that REM comments are always removed to the end of line by the operation of BASIC's CRUNCH.
		register names r0-r15 R0-R15 ap|AP (8) lc|LC (10) pp|PP (11) lp|LP (12) sp|SP (13) lr|LR (14) pc|PC (15) are recognised and substituted by the literal numbers.
		data directives DCD EQUD are converted to the short form '&'
		data directives DCS EQUS DCB EQUB DCW EQUW are converted to the short form ':='. Note that the short form ':=' is required to separate a possible preceding label. This is a bug or 'feature' of the BASIC assembler.
}
{Assembler macros
	Macros are functions included in assember that assemble code that may be modified by BASIC. If crunched, the names will no longer correspond to the library code that defines them.
	Preserving these names with Crunchie can be awkward. To exclude macro names use the keyword -macro or -mf followed by a macrofile name. This is a MessageTrans file, see below for details. This is only effective when the -assemble or -as switch is also used.
}
{Excluding variables
	By default Crunchie crunches all variable names. If it is necessary to exclude variable names, perhaps global values shared with a library, use the keyword -variable or -vf followed by a variablefile name. This file is a MessageTrans file, see below for details.
	Note that all variables with the same name will be excluded, but routine names are unaffected.
}
{Excluding routines
	By default Crunchie crunches all routine names, except those containg the character '@'. If it is necessary to exclude routine names, perhaps library routines, use the keyword -routine or -rf followed by a routinefile name. This file is a MessageTrans file, see below for details.
	Note that both a function and a procedure with the same name will be excluded.
	To help with library routines, all names with the same prefix, up to the character '_', can be excluded using that prefix as the token, eg: 'MyLib_'.
	Although not recommended for general use, crunching of all routine names can be stopped with the keyword -alloff or -ao. This is useful when debugging crunched code.
	For a possible library mechanism Crunchie will substitute a value following ':' for the name. This is to be developed.
}
{DATA lines
	By default Crunchie crunches the contents of DATA lines. This can cause problems.
	When BASIC READs a DATA item as a numeric value it does an evaluation of the item, which might include variables, although it cannot include BASIC functions, because DATA lines are not tokenised. This works with a crunched program because the item itself crunched.
	When BASIC READs a DATA item as a string value it does not evaluate it, but takes it as a literal. This will not work with a crunched program, because each word of the item is crunched.
	There are three ways to avoid this:
		Enclose all string items in quotes, which prevents them being crunched.
		Use the keyword -dataoff or -do, which will prevent all data items being crunched. This will mean that numeric data items cannot include variables.
		Exclude all variables that appear in numeric data items from crunching.
	All crunching programs have this problem.
}
{NEXT statements
	By default Crunchie removes loop variables following NEXT. If it is possible that the program exploits non-nested FOR...NEXT loops or the multiple NEXT syntax, then this can be disabled using the keyword -nextoff or -no.
}
{Concatenating lines
	By default Crunchie joins consecutive lines, where possible. Joining lines can be disabled using the keyword -joinoff or -jo.
	By default Crunchie does not join lines of a definiton to DEF statements, to allow for multiple-entry definitions. Joining these can be enabled using the keyword -defjoin or -dj.
	If deletion of empty lines is disabled with -emptyoff or -eo, this will disable joining lines, because joining would create empty lines.
}
{Libraries and crunching
	As a shared resource, a BASIC library should only use local variables, which can be satisfactorily crunched without problems.
	On the other hand, it should have unique main routine names that can be called by a program using the library, and these should not be crunched. Crunchie provides a simple method of preserving routine names with a single prefix.
	Library subroutines that are not used outside the library should also be unique, and these can be preserved by using the '@' character in their names,eg:
>	DEFPROCMyLib_This
>	 LOCAL this, that%, other%
>	 PROCMyLib@That(other%)
>	ENDPROC
>
>	DEFPROCMyLib@That(this%)
>	 ...
>	ENDPROC
	Sometimes a programmer uses library files that are unique to an application and in that case routine names can be crunched. The two ways to do this are in the next sections.
}
{Libraries file
	Library files and the main program can be crunched at the same time using the keyword -library or -lf followed by a libraryfile name.
	This file comprises a sequence of lines starting with the full name of a library to crunch, followed after spaces by the full name of the crunched file to save. Comments lines can be included starting with '#'.
	[calling libraries]
}
{Append libraries
	A library file that is specified by a literal LIBRARY "libname" anywhere in the program or any crunched libraries will be appended to the main program if the keyword -append or -ap is used. This must be followed by the maximum number of libraries expected, which is used to create the array to hold the library names.
	If the size of any possible appended library is greater than the size of the main program then the keyword -maxapp [-ma] must be used. This is followed by the size in bytes.
	When  a library is appended it retains the first line if it starts with REM>, as it always should. After all the libraries are appended, the whole program is renumbered from 1 in steps of 1. There is an error if the maximum number of lines is reached.
	If the -progress switch is on the Reporter window will show the line number and first line name of each appended library. This allows errors in the crunched program to be located to the source.
}
{Display progress
	It may be useful to see the progress of the crunching. To do this you will need Reporter running and then use the switch -progress or -pr. Then Crunchie shows:
		the name of the source program or library being crunched on a yellow background.
		the number of each line on which crunching occurs, followed by:
		a called routine in dark blue followed by the substituted call; a routine definition is on a dark blue background.
		a variable in dark green followed by the substituted variable; the first assignement of a variable is on a dark green background
		aliteral definition (LET=) on a light blue background; each substitution is shown in light blue.
		an EVAL keyword followed by an attempt at displaying the evaluated expression on an red background; EVAL is always tricky for crunching programs.
		a DATA statement in red in full as it appears in the program; if variables are crunched they will appear on the following lines.
		on completion the name of the crunched output program or library on a yellow background.
		at the end, the size of the source file, the size of the program and the size of the corresponding output file, each on a white background, then, if there has been more than one file, the same for the total.
	If a routine or variable 'name' is not crunched by the rules in force, it is not shown. (this could easily be changed)
	You may need to increase Reporter's Text Size in Config... to accomodate all the output.
	The output can be saved from the Reporter window menu.
}
{Record changes
	It may be useful to record the changes made by crunching, perhaps for analysis. One way is to use the method in 'Display progress' above.
	An alternative is to use the keyword -analysis or -af followed by an analysisfile name. Crunchie will then output a tab-separated file of detailed information on the crunching.
}
{Basalt programs
	My Basalt module allows the use of many more BASIC keywords as well as many other features. Crunchie would crunch these keywords and render them unreconisable. For Basalt progams use the switch -basalt or -ba and Crunchie will:
		Preserve Basalt keywords.
		Preserve Basalt constant names, which start with '@'. These are translated to literal values by Basalt itself. See also 'Transaltion'.
		Preserve the initial character of Basalt local list variables, which start with '_' or '`'. The remaining part of the 'name' is crunched to two characters.
	Always crunch the program before translation.
	The Basalt exclusions are in the file 'Basalt' in the 'Files' directory.
}
{MessageTrans files
	MessageTrans files for Crunchie comprise a list of names as tokens. For variable and routine names the token is the name and the value is the null string. That means the token is followed by a ':' only.
	However, the MessageTrans file format allows some shortening. Name tokens can be written one to a line /without/ the colon as long as the very last token is followed by a ':', which may be on a separate line. Also, any number of tokens may be joined on the same line, separated by '/'.
	MessageTrans tokens may include the wildcard character '?' which stands for any single character. There is no multiple-character wildcard.
	To ensure correct operation when using null values, the last line of the file must be a comment, say "#end".
	Lines must be terminated by a linefeed, character 10.
	Note that the MessageTrans file for assembly mnemonics has a slightly more complex structure to allow for the presence of condition codes etc. This is documented in the file.
}
]
[Translation
{Outline
	Crunchie is primarily intended to take a program that runs and has been debugged as its input. However, there are some useful features that can be included in a program, that prevent it being run directly, Crunchie can translate it to a runnable executable. Translation is enabled with the -translate or -tr switch.
	If the keyword -basalt or -ba is used there will be no translation, because Basalt will do this when the program runs.
	To emphasise, the program has to be crunched before it can be run.
}
{Event constants
	In other languages, say C, names of events are included in the source file and used where a number might otherwise be required. The names are converted to their numeric values when compiled. Translation does this for a BASIC program.
	An event name is written in the program prefixed by '@', eg: @Wimp_ScrollRequest, which is replaced by the literal number '10'.
	The events available are Wimp events, Toolbox events and a selection of common Message numbers. They are found in the MessageTrans file 'Events' in the 'Files' directory. This can be updated.
}
{User constants
	To make a program more readable it is useful to define constants by name, rather than assign variables, or use literal values that all have to be changed if the value of the constant changes.
	A file of constants can be used with the keyword -constants or -cf followed by a constantsfile name. The format is the same as for the Events file.
}
{COMAL routines
	COMAL is a language very like BASIC, which was available on the BBC micro. One of its useful features was that procedure and function calls did not have to be prefixed with PROC or FN. This has been likened to writing new keywords.
	Translation will implement this, but there are some constraints:
		no routine 'name' can be the same as a variable 'name'.
		routine names containing the character '@' must be called with PROC or FN.
		routine names may not start with a BASIC keyword.
		routine definitions, DEF PROC or DEF FN, must be present. If library routines are to be used they must either be called with PROC or FN or the library must be crunched along with the program.
	PROC and FN can always be used as usual.
}
{Program tags
	Although the use of GOTO and GOSUB are to be discouraged, they are also limited, because the program line number has to be known and preserved. This does not suit programs edited without line numbers.
	A tag is the character '#' followed by an alpahanumeric identitifier, eg: #tag1.
	A tag in a program must be at the start of a line. Everything else on the same line is treated as a REM as the program runs, except when the tag is used - see below.
	On translation, any tag after GOTO, GOSUB or RESTORE is replaced by the literal line number of the tag in the program. If the tag value does not exist it is ignored and will generate an error when run.
	The tag line itself is removed and the line joined to the following line, which preserves the target line number.
	Note:
		The last tag in a program with the same name will be the one recognised
		A tag after APPEND will still be recognised, but will be meaningless.
		Tags cannot be used in libraries.
	A Basalt tag does a jump to a program address and is faster, more flexible and can be used in libraries.
}
{ON and OFF
	ON and OFF are translated to TRUE and FALSE when not used as statements. This might make them useful synonyms.
}
{RETURN value
	RETURN followed by a value in a DEF FN is translated to the character '='.
}
{END structure
	END followed by a space and CASE, WHILE, PROC or IF are translated to the single tokens. This might make for a better presentation of a program.
	END followed by FN, with or without a space, is translated to '=FALSE'. This is for when a DEF FN is called as a statement and does not return a value, or as a dummy where the exit is within the function.
}
{ENDCASE early
	It is sometimes convenient to exit a CASE structure from the middle of a WHEN clause. A quirk of the interpreter means that a hanging WHEN statement does this. Crunchie translates ENDCASE that is not at the start of a line to WHEN.
}
{ENDIF early
	It is sometimes convenient to exit a multi-line IF structure from the middle of a clause. A quirk of the interpreter means that a hanging ELSE statement would do this. Crunchie translates ENDIF that is not at the start of a line to  the multi-line ELSE, token &CC.
}
{Nested errors
	This enables nested error handling of a form met in C++ or Java:
>	ERROR LOCAL
>	  <try statement>
>	WHEN error1,error2
>	  <catch error 1 or 2>
>	WHEN error3
>	  <catch error 3>
>	ERROR RESTORE
>	  <finally>
	This only works with BASIC from RISC OS 5.
	ERROR LOCAL is translated to:
>	LOCAL ERROR:ON ERROR LOCAL:!&8680=0:CASE ERR OF
>	WHEN FALSE
	!&8680=0 sets the last error number (ERR) to 0. This invokes the first WHEN FALSE as the 'try' clause. Note that error 0 cannot be trapped in BASIC.
	Other WHEN clauses will 'catch' errors according the their parameters.
	ERROR RESTORE is translated to:
>	OTHERWISE RESTORE ERROR:IF FN@@
>	ENDCASE:RESTORE ERROR
	The OTHERWISE line passes errors that have not been caught to the previous error handler using FN@@. If not, the ENDCASE line starts the 'finally' clause.
	The definition of FN@@ is included in the program if it has not already been. It is defined on one line and is not otherwise executed. The operation of FN@@ is not explained here!
>	DEFFN@@:LOCAL A%:DIM A% LOCAL TRUE:A%!-8=!&8684:=TRUE
}
{Multiple ELSEIF
	An alternative to a CASE structure is a set of nested multi-line IF structures. Instead of indenting, these can be formatted as:
>	IF a THEN
>	 <do a>
>	ELSEIF b THEN
>	 <do b>
>	ELSEIF c THEN
>	 <do c>
>	ELSE
>	 <default>
>	ENDIF
>	ENDIF
>	ENDIF
There must be as many ENDIFs as IFs.
	Other languages have an ELSEIF keyword that only requires one exit. Crunchie will translate code containing ELSEIF, as above, and ensure it has the correct number of ENDIFs, even if there is only one present. This is experimental.
}
{^ formal parameter (to be implemented)
	A '^' character before a parameter in DEF FN|PROC is translated to the RETURN keyword.
}
{FN statement (to be implemented)
	FN used as a statement is translated to WIDTH FN, which calls the function and discards the result. This means that WIDTH is given the value 0, which is its default and is very rarely changed.
	There is a small technical use for this, because function calls clear the workspace and procedure calls do not.
}
{End of DATA (to be implemented)
	DATA used as a function is translated to '?!&85F4=44'. If TRUE this shows that the data pointer is to a comma, indicating there is more data in that DATA statement. So:
>	REPEAT:READ value:UNTIL NOT DATA
}
{TIME pseudo-variable (to be implemented)
	BASIC should never alter the system time, which TIME= does. TIME= generates an error in Crunchie.
}
{CLOSE#0 (to be implemented)
	CLOSE#0 closes all open files, which will may have unintended consequences for other applications. Crunchie translates:
>	CLOSE# var
	to
>	var=var:IF var CLOSE# var
}
]
[Warnings
{First line
	Crunchie does not crunch the first line of programs and libraries.
	Crunchie expects the first line to start with REM> and then the file name of the program. This has been a standard practice from the earliest day of Arthur.
	If the author and/or version number are included, they are best separated by a TAB from the file name. This will keep error reporting clearer.
}
{Crunch speed
	Crunchie is fastest when no exclusions are applied.
}
{Program style
	Programs should be 'well-formed', without shortening tricks, particularly:
		a single-line IF statement must use THEN, or have ELSE on its own
		every FOR should have a corresponding NEXT - no NEXT i%,j%
		WHILE <condition> should be followed by : or a new line
		OTHERWISE should be followed by : or a new line
	Crunchie will mostly deal with programs that do not do this, but there will be cases where it fails without warning.
	Early exits from a PROC or FN are fine.
	Multi-entry DEFinitions are fine, unless the -defjoin switch is used.
}
{Using libraries
	If a program uses libraries, care should be taken to preserve routine names and global variables shared across program and libraries.
}
{Using assembler
	The implementation preserving assembler mnemonics is experimental, but should be fine for most simple coding.
	However, to ensure that Crunchie is happy the program should take account of the following:
		mnemonics must be in all uppercase or all lowercase - no mixed case.
		mnemonics must be treated as keywords, ie: no variable used in the assembled code should start with one - note the point above.
		named registers are tricky and best dealt with as literal definitions using LET.
	The assembler crunching is likely to be changed in due course.
}
{Using EVAL
	Clever tricks using EVAL on variable names and READing data which
contains variable names may not work, because the names can alter at runtime.
	The use of single character names or '@' in routine names may get around this problem.
}
{Using TOP
	The BASIC keyword TOP is not tokenised as iteself, but as TO followed by the character 'P'. There are obscure situations where crunching might cause problems and some crunching programs have to take special precautions. Crunchie should not have these, because it never crunches single-character names.
}
{CHR$ bugs
	When Crunchie crunches a non-printing character with CHR$ into a literal string there is the possibility of triggering a bug in BASIC; the interpreter does not reliably skip strings when scanning forward in a program line. For example, if the character &8B, the token for ELSE, is included in a string in a single-line IF, it will be found before the actual keyword.
	Control characters included in strings may make a crunched program unloadable, not just uneditable.
}
{Non-progam content
	Garbage in programs, eg: comments between definitions, may well be corrupted and will not be removed. Always use REMs to avoid this.
	Alternatively, crunching can be controlled using keywords CRUNCH ON|OFF and APPEND - see Operation>Unwanted routines.
}
{Editing programs
	Crunched programs may be impossible to edit, as lines may detokenise
to longer than 256 bytes and lack of spaces may confuse the
tokeniser.
}
]
[History
{0.93 07 Apr 2021
	New resource application icon.
	Removed the files for the !Crunchie Toolbox application.
		Omitting copyright message for Appended libraries or NoRem switch caused the next effective line after the first line to be deleted.
		LOCAL var%:LOCAL ERROR|DATA was crunched to LOCAL var%,ERROR|DATA.
		LOCAL ERROR:ON ERROR LOCAL RESTORE ERROR also crunched incorrectly.
		BY IF LN OF ON OR PI TO might be generated as variable names and only BY was eliminated.
}
{0.92 12 Apr 2021
	Introduced a switch, -norem [-nr], to disable the insertion of the copyright REM at the start of a crunched program. This is prompted by the CodeCraft competition.
		The switches for multiple LOCAL|DIM|READ|VDU were not reset at the end of a statement, leading to an error in joining lines in some circumstances.
	Some layout changes to this manual.
}
{0.91 09 Feb 2021
	Some improvement in the ease of reporting progress by using the SWI "Report_Text0" rather than *Report.
}
{0.90 06 Feb 2021
		In a copy & paste of 'Library' was not changed to 'Append' causing an error in Progress with Appended libraries.
		A duplicate use of a token in Files>Messages caused incorrect output of Progress with Appended libraries.
	There is some simplification of use of Messages and tokens.
	Reporting EVAL functions is tricky because of enclosing '()'. There is some improvement, but this may still cause errors. A simple warning can be given instead by uncommenting 'PEW' in Files>Messages.
	Line numbers in Progress are now right-aligned and the total line length is reduced.
}
{0.89 19 Jan 2021
	These ZeroPain errors were found by Martin Avison and could cause program errors:
		The temporary setting of BASIC$Crunch when it does not exist was to an integer rather than a string.
		A typing error in the code for initialising -maxapp prevented setting of maximum size.
		TRACE [STEP] PROC|FN was assumed to be including a routine call and was crunched.
}
{0.88 16 Oct 2020
	Combining of LOCAL statements did not take into account LOCAL DATA and LOCAL ERROR.
		There was an error in the Res file that crashed the Crunchie application from Export>Keywords.
}
{0.87 24 Feb 2020
	Yet more rationalisation and documentation of code to aid debugging.
		some variable names had not been changed correctly throughout the progam.
		the system variable name BASIC$Crunch had been corrupted by a poor search and replace.
	Consecutive LOCAL, READ, DIM and VDU statements are combined into comma-separated lists. This is also done over line breaks if lines can be joined.
	Progress display is improved - possibly.
	Analysis is now presented as a tab-separated file, which can be imported to a spreadsheet.
	Nearly all program strings are now stored in Crunchie:File.Messages, which allows for simple editing and internationalisation.
}
{0.86 05 Dec 2019
		I left a *Shut in the error code - a major blunder.
		There was a bug caused by double commas in the analysis code.
	There are still some other unresolved issues, so an unreliable release.
}
{0.85 06 Nov 2019
	A lot more rationalisation of code.
	Control of crunching has been introduced. By default all of a program or library is crunched, but if the keywords CRUNCH ON are used, all the code back to a preceding CRUNCH OFF will be omitted. There is an implicit CRUNCH OFF after the initial REM lines.
	This allows for test code at the start of a library that is not required when used, with just CRUNCH ON before the definitions.
}
{0.84 24 Oct 2019
	A lot of rationalisation of code.
	If the size of any possible appended library is greater than the size of the main program then the keyword -maxapp [-ma] must be used. This is followed by the size in bytes. See 'Appended libraries'.
	There are now separate name lists for procedures, functions, integers, strings and floats, and for the three types of array. Name exclusions still operate on all routine names or all variable names.
	The amount of detail appearing in the Reporter window with -progress has been reduced, along with some colour changes. The information in the -analysis file has been increased.
}
{0.83 14 Oct 2019
	In transalation a line starting with DEF only is converted to a tokenised DATA line. (experimental, yet to be documented)
	If the keyword -append [-ap] is used, libraries specified by a literal LIBRARY "libname" anywhere in the program or any crunched libraries will be appended to the main program. See 'Appended libraries'.
}
{0.82 11 Oct 2019
		command line keywords could be confused when abbreviated to a single letter.
	Except for -input [-i] and -output [-o], which are not compulsory, all keywords must now be used in full, or with the designated two-letter abbreviations. See Syntax.
}
{0.81 10 Oct 2019
	Added switch to enable joining of lines after DEF. This is not done by default, to allow multi-entry routines.
	Names are now held in local variable lists. This is less clumsy and more flexible. It also removes the limitation of single-character string names in Crunchie itself.
	Integers, Strings and Floats now have independent lists, each limited to 3197. Variables and arrays still share names.
	The routines list is now limited to 3844. PROCs and FNs still share names.
	Routine and Variable code edited to be more succinct.
	Analysis output file implemented to record all crunched names.
	Literal substitution with LET is more robust and now allows integer, string and float literals. Literals can be switched off with -litoff or -i (note that is 'i')
	The crunching of all routine names can be disabled with -alloff  or -o  (note that is 'o'). This is not recommended, but can be useful when debugging crunched files.
	There are some changes to the summary and statistics in the Reporter window.
}
{0.80 03 Oct 2019
		reporting of routines had been disabled by mistake.
	Reporting restored.
}
{0.79 02 Oct 2019
		a combination of line numbers and tags showed up a problem with the tag code.
	Tag code now works only with the Translate switch. Determining line start is more carefully evaluated.
	Crunchie now has a Toolbox front end. Previous experimental version used Basalt, but this version uses only BASIC and my Oobi OOP interface.
}
{0.78 03 Feb 2019
	After a long hiatus.
	Corrected an error using an old version. This version is invalid
}
{0.77 08 Jan 2019
		routine generating names was missing out whole ranges.
	Routine corrected.
		with large number of crunched variables Crunchie ran out of memory.
	Automatic memory adjustment should keep sufficient available.
}
{0.76 07 Jan 2019
		v0.75 introduced a serious error
	This has been corrected - probably.
}
{0.75 04 Jan 2019
		it is possible to create names that are recognised by the assembler as registers and there is a very small chance that this will cause an error.
	If the -assemble switch is on the names r0-r9 sp lr pc, and other case versions, are not created.
		it is possible to create the name BY, which is an untokenised keyword only used by MOVE DRAW FILL POINT and there is a very small chance that this will cause an error.
	The name BY is never created.
	Crunchie inserts a line after the first, REM>, line:
>	REM Crunched by Crunchie version n.nn (dd mmm yyyy)
}
{0.74 04 Jan 2019
		the -libraries file was being parsed incorrectly when there were comments, resulting in the omission of some files.
	Parsing now ignores comments correctly.
		there were some multiline THEN keyords followed by :REM comments, which would not be removed if run without Basic$Crunch set. The same for a couple of OF:REM.
	These comments have been moved.
}
{0.73 03 Jan 2019
		line number encoding following token &8D was not preserved. This affects GOTO GOSUB RESTORE and maybe THEN ELSE
	The token and following 3 bytes are copied without crunching.
}
{0.72 03 Jan 2019
		CHR$ with argument equal to 13 cannot be inserted as a literal into a BASIC program line.
	Exclude this from crunching and also value for ELSE token.
		Assembler Opcodes are only recognised in uppercase.
	Adapt Assemble file to allow lowercase, but not mixed case.
}
{0.71 29 Dec 2018
		First Release
	It should be considered to be very much beta, and all comments are welcome.
}
]
[Author
	Crunchie is written by Steve Drain:
>	http://www.kappa.me.uk
>	mailto:steve@kappa.me.uk
	Comments and bug reports are always welcome.
]
